package Model;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

/**
 *
 * @author kiko
 */
public class AtendeCliente extends Thread {
    ServerSocket welcomeClient;
    ArrayList<Socket> clientList;
    ServerAplication serverAplication;
    ServerList serverList;
            
    public AtendeCliente(ServerSocket welcomeClient, ServerAplication serverAplication, ServerList serverList) {
        this.welcomeClient = welcomeClient;
        this.clientList = new ArrayList();
        this.serverAplication = serverAplication;
        this.serverList = serverList;
    }

    @Override
    public void run() {
        try {
            while (true) {
                final Socket aux = welcomeClient.accept();
                new CMessageReceiver(aux, this).start();
                clientList.add(aux);
            }
        } catch (IOException ex) {
            System.out.println("O AtendeCliente falhou ao tentar receber conexao");
        }
    }
    
    public ArrayList<Socket> getServerList() {
        return serverList;
    }
    
    public void receiveFile(Socket connection) {
        ObjectInputStream inputArc;
        String fileName = null;
        try {
            inputArc = new ObjectInputStream(new BufferedInputStream(connection.getInputStream()));
            fileName = inputArc.readUTF();
            long size = inputArc.readLong();
            String path = fileName;
            BufferedOutputStream saveArq = new BufferedOutputStream(new FileOutputStream(path));
            byte[] buf = new byte[4096];
            int temp = 0;
            while (true) {
                int len;
                if (size - temp > 0) {
                    len = inputArc.read(buf);
                } else {
                    saveArq.close();
                    break;
                }
                temp = temp + len;

                saveArq.write(buf, 0, len);
                saveArq.flush();
            }
            inputArc.close();
        } catch (IOException ex) {
            System.out.println("Erro ao tentar responder mensagem");
        }
        serverAplication.warnUpdate(fileName);
    }
    
    public void sendFile(Socket conection, String fileName) {
        try {
            File file = new File(fileName);
            ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(conection.getOutputStream()));
            out.writeUTF(file.getName());
            out.writeLong(file.length());
            BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));

            byte[] buf = new byte[4096];
            while (true) {
                int len = in.read(buf);
                if (len == -1) {
                    break;
                }
                out.write(buf, 0, len);
                out.flush();
            }
            System.out.println("Arquivo enviado com sucesso");
            in.close();
        } catch (FileNotFoundException ex) {
            System.out.println("Erro: Arquivo não encontrado");
        } catch (IOException ex) {
            System.out.println("O AtendeCliente falhou ao tentar enviar o arquivo " + fileName);
        }
    }
    
    public void permissionToModify(Socket conection, String fileName, String keyword) {
        try {
            String path = "permissions" + File.separator + fileName;
            BufferedReader in = new BufferedReader(new FileReader(path));
            String str = in.readLine();
            in.close();
            if (str.equals("nobody") || str.equals(keyword)) {
                DataOutputStream dos;
                ServerList<Socket> serverList = serverAplication.getServerList();
                String word = generateRandomWord();
                for (int i = 0; i < serverList.size(); i++) {
                    Socket socketAux = serverList.get(i);
                    dos = new DataOutputStream(socketAux.getOutputStream());
                    dos.writeBytes("PERM:" + path + ":" + word + "\n");
                }
                BufferedWriter out = new BufferedWriter(new FileWriter(path));
                out.write(word + "\n");
                out.close();
                dos = new DataOutputStream(conection.getOutputStream());
                dos.writeBytes("PGRA:" + word + ":" + fileName + "\n");
            } else {
                
                DataOutputStream dos = new DataOutputStream(conection.getOutputStream());
                dos.writeBytes("PDEN\n");
            }
        } catch (IOException e) {
            System.out.println("Erro! Nao foi possivel ler o arquivo.");
        }
    }
    
    private String generateRandomWord() {
        String[] letras = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"};
        int aleatorio;
        StringBuilder builder = new StringBuilder();

        for (int i = 1; i <= 10; i++) {
            aleatorio = (int) (Math.random() * (letras.length - 1));
            builder.append(letras[aleatorio]);
        }
        
        return builder.toString();
    }
    
    public void removeFromList(Socket aux) {
        clientList.remove(aux);
        System.out.println("Fim de conexão com: " + aux.getInetAddress().toString());
    }
}
/*
autenticação dos usuários
arquitetura do sistema de arquivos
download e upload de arquivos
consistência das réplicas
balanceamento de carga nos servidores
*/